package org.blade.personal.framework.dsl.sql;

import org.blade.personal.engine.DdlKeyWord;
import org.blade.personal.framework.dsl.Clause;
import org.blade.personal.framework.dsl.corcre.MySQLSqlClauseFactory;
import org.blade.personal.framework.dsl.corcre.SqlClauseFactory;
import org.blade.personal.framework.orm.EntityAlias;
import org.blade.personal.framework.orm.TypeAlias;
import org.blade.personal.framework.session.ResultHandler;
import org.blade.personal.framework.session.concre.ConcreResultHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 抽象子句类
 * @author ZGF
 *
 * @param 
 */
public abstract class AbstractSql implements Sql {

	/**
	 * 日志
	 */
	private Logger logger = LoggerFactory.getLogger(getClass()); 
	
	/**
	 * 子句
	 */
	protected Clause clause;
	
	/**
	 * 别名
	 */
	protected String alias;
	
	/**
	 * 实体结果辅助器
	 */
	protected ResultHandler resultHandler ;
	
	
	//暂时先实现MySQL的子句
	private SqlClauseFactory  factory = new MySQLSqlClauseFactory();
	
	
	
	
	
	/**
	 * 构造带别人的SQL，一般用于要子查询语句的时候
	 * @param alise
	 */
	public AbstractSql(String alise) {
		this.alias = alise;
	}
	
	public AbstractSql() {
		this.alias = "";
	}
	
	/**
	 * 为属性设置别名
	 * @param alise
	 * @param attribute
	 * @return
	 */
	private TypeAlias appendAttributeAlise(String alise, TypeAlias attribute ){
		
		if(null == alise || "".equals(alise)){
			return attribute; 
		}
		return attribute.setAlise(alise);
	}
	
	@Override
	public Sql select(TypeAlias... alies) {
		this.resultHandler = new ConcreResultHandler();
		StringBuilder clause = new StringBuilder();
		clause.append(DdlKeyWord.SELECT);
		
		for(int i = 0 ; i < alies.length ; i++){
			//TODO 需要改进
			TypeAlias aliseCopied = alies[i].clone();
			//添加到结果实体辅助器绑定
			resultHandler.setResultEntityAttribute(aliseCopied);
			clause.append(DdlKeyWord.SPACE).append(aliseCopied.getClause());

			if( i+1 < alies.length){
				clause.append(",");
			}
		}
		this.clause = factory.build(clause.toString());
		return this;
	}
	
	@Override
	public Sql from(EntityAlias entity) {
		
		StringBuilder clause = new StringBuilder();
		clause.append(DdlKeyWord.FROM).append(DdlKeyWord.SPACE)
		.append(DdlKeyWord.SPACE).append(entity.getTable())
		.append(DdlKeyWord.SPACE).append(entity.getAlise());
		if(this.clause != null){
			this.clause.setClause(factory.build(clause.toString()));
		}else{
			this.clause = factory.build(clause.toString());
		}
		return this;
	}
	@Override
	public Sql where(TypeAlias... alies) {
		StringBuilder clause = new StringBuilder();
		clause.append(DdlKeyWord.WHERE).append(DdlKeyWord.SPACE)
		.append(DdlKeyWord.WHERE_ONE_EQ_ONE);
		for(int i = 0 ; i < alies.length ; i++){
			clause.append(DdlKeyWord.SPACE)
			.append(DdlKeyWord.AND)
			.append(alies[i].getClause());
		}
		this.clause.setClause(factory.build(clause.toString()));
		return this;
	}

	@Override
	public Sql and(TypeAlias alies) {
		StringBuilder clause = new StringBuilder();
		clause.append(DdlKeyWord.AND).append(DdlKeyWord.SPACE)
		.append(alies.getClause());
		this.clause.setClause(factory.build(clause.toString()));
		return this;
	}

	@Override
	public Sql from(Sql sql) {
		this.alias = sql.getAlise();
		StringBuilder clause = new StringBuilder();
		clause.append(DdlKeyWord.FROM).append("(")
		.append(sql.get()).append(")").append(DdlKeyWord.SPACE)
		.append(sql.getAlise());
		this.clause.setClause(factory.build(clause.toString()));
		return this;
	}

	@Override
	public Sql list(TypeAlias... alies) {
		
		//TODO resultHandler使用Factory来创建实例不去依赖具体的实现类
		this.resultHandler = new ConcreResultHandler();
		//TODO 多数据版本时这里需要支持多库
		SqlClauseFactory  factory = new MySQLSqlClauseFactory();
		StringBuilder sql = new StringBuilder(this.get());
		Clause clause = factory.build(sql.toString());
		
		StringBuilder selectClauseBuff = new StringBuilder(DdlKeyWord.SELECT);
		for(int i = 0 ; i < alies.length ; i++){
			//TODO 需要改进
			TypeAlias aliseCopied = alies[i].clone();
			this.resultHandler.setResultEntityAttribute(aliseCopied);
			
			debug(aliseCopied.getClause());
			selectClauseBuff.append(DdlKeyWord.SPACE)
			.append(aliseCopied.getClause());
			
			if( i+1 < alies.length){
				selectClauseBuff.append(",");
			}
		}
		Clause selectClause = factory.build(selectClauseBuff.toString());
		selectClause.setClause(clause);
		this.clause = selectClause;
		return this;
	}

	@Override
	public Sql union(Sql sql) {
		
		StringBuilder clause = new StringBuilder();
		clause.append(DdlKeyWord.UNION).append("(")
		.append(sql.get()).append(")")
		.append(this.alias);
		this.clause.setClause(factory.build(clause.toString()));
		return this;
	}

	@Override
	public Sql unionAll(Sql sql) {
		StringBuilder clause = new StringBuilder();
		clause.append(DdlKeyWord.UNION_ALL).append("(")
		.append(sql.get()).append(")")
		.append(this.alias);
		this.clause .setClause(factory.build(clause.toString()));
		return this;
	}
	
	@Override
	public String get() {
		return this.clause.build();
	}
	
	@Override
	public String getAlise() {
		return this.alias;
	}
	
	
	@Override
	public Sql join(EntityAlias entity) {
		
		StringBuilder clause = new StringBuilder();
		clause.append(DdlKeyWord.JOIN)
		.append(entity.getTable()).append(DdlKeyWord.SPACE)
		.append(entity.getAlise());
		this.clause.setClause(factory.build(clause.toString()));
		return this;
	}
	
	@Override
	public Sql join(Sql sql) {
		StringBuilder clause = new StringBuilder();
		clause.append(DdlKeyWord.JOIN).append("(")
		.append(sql.get()).append(DdlKeyWord.SPACE)
		.append(")").append(sql.getAlise());
		this.clause.setClause(factory.build(clause.toString()));
		return this;
	}
	
	@Override
	public Sql leftJoin(EntityAlias entity) {
		StringBuilder clause = new StringBuilder();
		clause.append(DdlKeyWord.LEFT_JOIN)
		.append(entity.getTable()).append(DdlKeyWord.SPACE)
		.append(entity.getAlise());
		this.clause.setClause(factory.build(clause.toString()));
		return this;
	}
	
	@Override
	public Sql leftJoin(Sql sql) {
		StringBuilder clause = new StringBuilder();
		clause.append(DdlKeyWord.LEFT_JOIN)
		.append(" ( ").append(sql.get())
		.append(" ) ").append(DdlKeyWord.SPACE).append(sql.getAlise());
		this.clause.setClause(factory.build(clause.toString()));
		return this;
	}
	
	@Override
	public Sql on(TypeAlias... alies) {
		// TODO 此处有链式表达式处理，暂时先实现成一个表达式
		//这里可以表达式方式实现
		StringBuilder clause = new StringBuilder();
		clause.append(DdlKeyWord.ON)
		.append(alies[0].getClause()).append(DdlKeyWord.SPACE);
		this.clause.setClause(factory.build(clause.toString()));
		return this;
	}
	
	@Override
	public Sql rightJoin(EntityAlias entity) {
		StringBuilder clause = new StringBuilder();
		clause.append(DdlKeyWord.RIGHT_JOIN)
		.append(entity.getTable()).append(DdlKeyWord.SPACE)
		.append(entity.getAlise());
		this.clause.setClause(factory.build(clause.toString()));
		return this;
	}
	
	@Override
	public Sql rightJoin(Sql sql) {
		StringBuilder clause = new StringBuilder();
		clause.append(DdlKeyWord.RIGHT_JOIN)
		.append(" ( ").append(sql.get())
		.append(" ) ").append(DdlKeyWord.SPACE).append(sql.getAlise());
		this.clause.setClause(factory.build(clause.toString()));
		return this;
	}
	
	@Override
	public Sql groupBy(TypeAlias... alies) {
		StringBuilder clause = new StringBuilder();
		clause.append(DdlKeyWord.GROUP_BY).append(DdlKeyWord.SPACE);
		for(int i = 0 ; i < alies.length ; i++){
			clause.append(DdlKeyWord.SPACE)
			.append(alies[i].getClause());
			if( i+1 < alies.length){
				clause.append(",");
			}
		}
		this.clause.setClause(factory.build(clause.toString()));
		return this;
	}
	
	@Override
	public Sql having(TypeAlias alies) {
		
		StringBuilder clause = new StringBuilder();
		clause.append(DdlKeyWord.HAVING).append(DdlKeyWord.SPACE);
		clause.append(DdlKeyWord.SPACE)
		.append(alies.getClause());
		this.clause.setClause(factory.build(clause.toString()));
		return this;
	}
	
	@Override
	public Sql orderBy(TypeAlias... alies) {

		StringBuilder clause = new StringBuilder();
		clause.append(DdlKeyWord.ORDER_BY).append(DdlKeyWord.SPACE);
		for(int i = 0 ; i < alies.length ; i++){
			clause.append(DdlKeyWord.SPACE)
			.append(alies[i].getClause());
			if( i+1 < alies.length){
				clause.append(",");
			}
		}
		this.clause.setClause(factory.build(clause.toString()));
		return this;
	}
	
	@Override
	public TypeAlias $(String rs) {
		// TODO Auto-generated method stub
		
		return null;
	}
	
	@Override
	public ResultHandler getResultHandler() {
		// TODO 
		return this.resultHandler;
	}
	
	private void debug(String log){
		if(logger.isDebugEnabled()){
			logger.debug(log);
		}
	}
	
	private void info(String log){
		logger.info(log);
	}
	
	private void error(String log){
		logger.error(log);
	}
	
	private void stdout(String log){
		System.out.println(log);
	}
	
}
